package io.jboot.admin.controller.led;

import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import cn.hutool.core.util.StrUtil;
import com.jfinal.kit.Kv;
import com.jfinal.kit.LogKit;
import com.jfinal.kit.StrKit;
import io.jboot.admin.base.web.base.BaseController;

/**
 * ×××××××××××××××××××××××××××××××××××××××××
 * 如果项目导入报错注意： 需要使用tomcat7+ JDK７＋　的版本
 * ×××××××××××××××××××××××××××××××××××××××××
 *
 * @author dufuzhong
 * @ServerEndpoint 注解是一个类层次的注解，它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 */
@ServerEndpoint("/led/websocket")
public class WebSocketController {

    //用来存放每个客户端对应的MyWebSocket对象。
    private static final Map<String, WebSocketController> WEB_SOCKET_MAP = new ConcurrentHashMap<String, WebSocketController>();
    private static final Map<String, Kv> WEB_KV = new ConcurrentHashMap<String, Kv>();
    private static String JIUBA_NAME = "";

    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;
    //UUID 生成的IDS
    private String ids;
    //name 昵称
    private String name;


    /**
     * 连接建立成功调用的方法
     *
     * @param session 可选的参数。session为与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(@PathParam("ids") String ids, Session session) {
        ids = session.getQueryString();
        String type = getTypebyid(ids);
        if (type.equals("led")) {
            //大屏本身是单节点部署，数据共享即可，这样一个酒吧数据连接节点,可以保障websocket性能
            this.ids = ids;
            this.session = session;
            WEB_SOCKET_MAP.put(ids, this);
            this.name = JIUBA_NAME;
            sendAllMessage("【系统信息】" + JIUBA_NAME + "上线");
        } else {
            //只存储很多用户数据
            this.ids = ids;
            this.session = session;
            WEB_SOCKET_MAP.put(ids, this);
            this.name = getKvByIds(ids).getStr("name");
            sendAllMessage("【系统信息】欢迎：" + this.name);
        }
    }

    private String getTypebyid(String ids) {
        if (ids.contains(":led:")) {
            return "led";
        }
        return "user";
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        WEB_SOCKET_MAP.remove(this.session);
        LogKit.info("有一连接关闭！当前在线人数为" + WEB_SOCKET_MAP.size());
        LogKit.info("session=" + session.getId());

        sendAllMessage("【系统信息】" + this.name + " 离开了", false);
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        LogKit.info("来自客户端的消息:" + message);
        LogKit.info("session=" + session.getId());

        sendAllMessage(this.name + "：" + message);
    }

    /**
     * 发生错误时调用
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        LogKit.error("发生错误", error);
    }

    /**
     * 发送群消息
     */
    protected void sendAllMessage(String message) {
        sendAllMessage(message, true);
    }

    /**
     * 发送群消息
     *
     * @param message 消息
     * @param isThis  是否给自己 也发
     */
    protected void sendAllMessage(String message, boolean isThis) {
        for (Entry<String, WebSocketController> entry : WEB_SOCKET_MAP.entrySet()) {
            //群发消息
            WebSocketController me = entry.getValue();
            if (isThis || me != this) {
                me.sendMessage(message);
            }
        }
    }

    /**
     * 指定 发送消息
     */
    protected void sendMessage(String ids, String message) {
        WebSocketController me = WEB_SOCKET_MAP.get(ids);
        if (me != null) {
            me.sendMessage(message);
        } else {
            this.sendMessage("【系统消息】" + getNameByIds(ids) + " 不在线");
            //留言系统 待开发
        }
    }

    /**
     * 向客户端 发送消息
     */
    protected void sendMessage(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            LogKit.error("客户端异常", e);
        }
        //this.session.getAsyncRemote().sendText(message);
    }

    public static Kv getKvByIds(String ids) {
        Kv kv = WEB_KV.get(ids);
        if (kv == null) {
            WEB_KV.put(ids, new Kv());
            return getKvByIds(ids);
        }
        return kv;
    }

    public static String getNameByIds(String ids) {
        return getKvByIds(ids).getStr("name");
    }

    public static String setNameByIds(String ids, String name) {
        if (StrKit.isBlank(name)) {
            name = "匿名";
        }
        Kv kv = getKvByIds(ids);
        if (!name.equals(kv.get("name"))) {
            kv.set("name", name);
            // 同步成员变量
            WebSocketController me = WEB_SOCKET_MAP.get(ids);
            if (me != null) {
                me.name = name;
            }
        }
        return name;
    }

    public static void setJiubaNameByIds(String name) {
        JIUBA_NAME = name;
    }
}
